package demo

import (
	"context"
	"fmt"
	"github.com/chromedp/cdproto/network"
	"github.com/chromedp/chromedp"
	"github.com/sirupsen/logrus"
	"time"
)

type HcyTest struct {
	webUri    string
	apiUri    string
	username  string
	pwd       string
	ctx       context.Context
	cancel    context.CancelFunc
	loginSign chan int // 登录信号
	endSign   chan int // 结束测试的信号
}

func New(openDebug bool) *HcyTest {
	obj := &HcyTest{
		webUri:    "https://gms-test.traingo.com.cn/login?redirect=%252F",
		apiUri:    "https://api.test.tgtrain.cn",
		username:  "hechongyang",
		pwd:       "12345678",
		ctx:       nil,
		cancel:    nil,
		loginSign: make(chan int, 1),
		endSign:   make(chan int, 1),
	}
	options := []chromedp.ExecAllocatorOption{
		chromedp.Flag("headless", openDebug), // 是否打开浏览器调试
		chromedp.UserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"), // 设置User-Agent
	}
	options = append(chromedp.DefaultExecAllocatorOptions[:], options...)
	// chromdp依赖context上限传递参数
	obj.ctx, obj.cancel = chromedp.NewExecAllocator(
		context.Background(),
		options...,
	)
	obj.ctx, obj.cancel = chromedp.NewContext(
		obj.ctx,
	)
	return obj
}
func (dp HcyTest) Run() {
	// 监听各种浏览器事件
	chromedp.ListenTarget(dp.ctx, func(ev interface{}) {
		switch ev := ev.(type) {
		// 浏览器开始处理http响应时触发的事件
		case *network.EventResponseReceived:
			switch ev.Type {
			case network.ResourceTypeXHR:
				var (
					log AjaxLog
					ok  bool
				)
				if log, ok = requestMap[ev.RequestID]; !ok {
					logrus.Error("未记录的请求:", ev.Response.URL)
				} else {
					log.EndTime = time.Now().Unix()
					log.Duration = log.EndTime - log.StartTime
					bs, err := ev.Response.MarshalJSON()
					if err != nil {
						logrus.Errorf("获取响应参数时发出错误：%v", err)
					}
					log.Data = string(bs)
				}
				requestMap[ev.RequestID] = log
				logrus.Infof("记录请求参数，uri：[%s],响应时间：[%d]ms,请求方式：[%s],响应数据：[%s]", log.Uri, log.Duration, log.Method, log.Data)
			case network.ResourceTypeWebSocket:
				logrus.Debug("websocket：", ev.Response.URL)
			case network.ResourceTypeFetch:
				logrus.Debug("请求 fetch 接口：", ev.Response.URL)
			}
		// 浏览器准备发起http请求前触发的事件
		case *network.EventRequestWillBeSent:
			allMap[ev.RequestID] = ev.Request.URL
			switch ev.Type {
			case network.ResourceTypeDocument:
				logrus.Debug("打开页面：", ev.Request.URL)
			case network.ResourceTypeXHR:
				log := AjaxLog{
					Page:      ev.DocumentURL,
					Uri:       ev.Request.URL,
					Method:    ev.Request.Method,
					Header:    ev.Request.Headers,
					Data:      "",
					StartTime: time.Now().Unix(),
					EndTime:   0,
					Duration:  0,
				}
				requestMap[ev.RequestID] = log
			case network.ResourceTypeWebSocket:
				logrus.Debug("websocket：")
			case network.ResourceTypeFetch:
				logrus.Debug("请求 fetch 接口：")
			}
		// 浏览器加载任意资源失败时触发的方法，也是功能测试需要重点检查的事件
		case *network.EventLoadingFailed:
			switch ev.Type {
			case network.ResourceTypeDocument:
				logrus.Errorf("请求页面失败：%s", allMap[ev.RequestID])
			case network.ResourceTypeXHR:
				logrus.Errorf("请求接口失败：%s", allMap[ev.RequestID])
			case network.ResourceTypeImage:
				logrus.Errorf("请求图片失败：%s", allMap[ev.RequestID])
			case network.ResourceTypeScript:
				logrus.Errorf("请求js脚本失败：%s", allMap[ev.RequestID])
			}
		}
	})

	// 执行各种测试操作
	err := chromedp.Run(
		dp.ctx,
		// 打开浏览器，访问首页
		chromedp.Navigate(dp.webUri),
		// 开始测试，自动化测试代码重这里开始自行填充
		dp.autoSubmitExam(),
	)
	if err != nil {
		fmt.Println(err)
	}
	_ = <-dp.endSign
	fmt.Println("自动化测试结束")
}
